<template>
  <Dialog v-model="dialogVisible" :title="dialogTitle">
    <el-steps :active="active" align-center>
      <el-step title="基本信息" />
      <el-step title="选择需求" />
    </el-steps>
    <div class="test-form" v-show="step1">
      <el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="100px">
        <el-form-item label="版本" prop="version">
          <el-select v-model="formData.version" clearable placeholder="请选择版本" :disabled="formType === 'view'">
            <el-option v-for="version in versionList" :key="version.id" :label="version.versionName"
              :value="version.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="地址" prop="deploy_package_address">
          <el-input v-model="formData.deploy_package_address" placeholder="请输入安装包地址或访问地址"
            :disabled="formType === 'view'" />
        </el-form-item>
        <el-form-item label="环境" prop="environment">
          <el-input v-model="formData.environment" placeholder="请输入测试环境，如：CentOS7等" :disabled="formType === 'view'" />
        </el-form-item>
        <el-form-item label="任务" prop="description">
          <el-input v-model="formData.description" placeholder="请输入任务简述" type="textarea"
            :disabled="formType === 'view'" />
        </el-form-item>
        <el-form-item label="附件" prop="file">
          <el-upload ref="uploadRef" v-model:file-list="files" :action="importUrl" :auto-upload="false"
            :disabled="formType === 'view'" :headers="uploadHeaders" :limit="3" :on-success="submitFormSuccess"
            :on-error="submitFormError" :on-exceed="handleExceed" :on-preview="handlePreview" drag style="width: 100%;">
            <Icon icon="ep:upload" />
            <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
            <template #tip>
              <div class="el-upload__tip text-center">
                <span>例如：设计文档、用户手册等项目文件。</span>
              </div>
            </template>
          </el-upload>
        </el-form-item>
      </el-form>
      <div class="test-form-footer">
        <el-button type="primary" @click="Next(formRef)">下一步</el-button>
        <el-button @click="dialogVisible = false">取消</el-button>
      </div>
    </div>
    <div v-show="step2">
      <div class="test-tree">
        <el-tree show-checkbox style="padding-left:5% ; width: 40%" :data="dataSource" ref="treeRef" node-key="id"
          default-expand-all :expand-on-click-node="false" :filter-node-method="filterNode" :props="defaultProps"
          :class="editDisabled ? 'disabled-tree' : ''" class="tree" :highlight-current="true" :indent="22"
          @node-click="handleNodeClick" :default-checked-keys="checkedNodes">
          <template #default="{ node, data }">
            <!-- 非叶子 -->
            <span v-if="!node.isLeaf" style="display: flex; align-items: center;" :class="{ 'disabled': data.isRoot }">
              <span @click.stop="node.expanded = !node.expanded">
                <el-icon v-if="node.expanded" style="margin: 0 6px 0 2px;" size="16">
                  <FolderOpened />
                </el-icon>
                <el-icon v-else style="margin: 0 6px 0 2px;" size="16">
                  <Folder />
                </el-icon>
              </span>
              <small>{{ node.label }}</small>
              <span v-if="data.demandNum > 0" class="num"> （{{ data.demandNum }}） </span>
            </span>
            <!-- 叶子 -->
            <span v-else style="display: flex; align-items: center;">
              <el-icon style="margin: 0 6px 0 2px;" size="16">
                <Document />
              </el-icon>
              <small>{{ node.label }}</small>
            </span>
          </template>
        </el-tree>
        <el-form v-if="nodeShow" style="width: 60%" ref="nodeRef" :model="nodeData" label-width="100px">
          <el-form-item label="名称:" prop="name">
            {{ nodeData.name }}
          </el-form-item>
          <el-form-item label="标识:" prop="code">
            {{ nodeData.code }}
          </el-form-item>
          <el-form-item label="描述:" prop="description">
            {{ nodeData.description }}
          </el-form-item>
          <el-form-item label="状态:" prop="status">
            {{ nodeData.status }}
          </el-form-item>
          <el-form-item label="开发责任人:" prop="developerId">
            {{ nodeData.developerId }}
          </el-form-item>
        </el-form>
      </div>
      <div class="test-form-footer">
        <el-button type="primary" @click="Back()">上一步</el-button>
        <el-button v-if="formType !== 'view'" type="primary" :disabled="submitDisabled"
          @click="submitForm()">暂存</el-button>
        <el-button @click="dialogVisible = false">取消</el-button>
      </div>
    </div>
  </Dialog>
</template>
<script lang="ts" setup>
import * as TestApi from '@/api/test'
import * as DemandApi from '@/api/demand'
import { FolderOpened, Folder, Document } from '@element-plus/icons-vue'
import { getAccessToken, getTenantId } from '@/utils/auth'

defineOptions({ name: 'TestForm' })

const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

let projectId = ref()
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中：1）修改时的数据加载；2）提交的按钮禁用
const formType = ref('') // 表单的类型：create - 新增；update - 修改
const formData = ref({
  version: '',
  deploy_package_address: '',
  environment: '',
  description: '',
  file: [],
  status: ''
})
const formRules = reactive({
  version: [{ required: true, message: '版本不能为空', trigger: 'blur' }],
  deploy_package_address: [{ required: true, message: '安装包地址不能为空', trigger: 'blur' }],
  description: [{ required: true, message: '任务不能为空', trigger: 'blur' }],

})
const formRef = ref() // 表单 Ref
/** 重置表单 */
const resetForm = () => {
  formData.value = {
    version: '',
    deploy_package_address: '',
    environment: '',
    description: '',
    file: [],
    status: ''
  }
  formRef.value?.resetFields()
  nodeData.value = {
    name: '',
    code: '',
    description: '',
    status: '',
    developerId: ''
  }
  nodeRef.value?.resetFields()
  uploadRef.value?.clearFiles()
  files.value = []
  editDisabled.value = false
  checkedNodes.value = []
}
/** 打开弹窗 */
const open = async (type: string, id?: number, projectid?: number) => {
  dialogVisible.value = true
  dialogTitle.value = t('action.' + type)
  formType.value = type
  active.value = 0
  step1.value = true
  step2.value = false
  nodeShow.value = false
  projectId = projectid.value
  getversionList()
  getStatusList()
  getDutyList()
  resetForm()
  // 修改时，设置数据
  if (id) {
    formLoading.value = true
    try {
      const data = await TestApi.viewTest({ id: id })
      formData.value.id = data.id
      formData.value.version = data.version.id
      formData.value.deploy_package_address = data.deploy_package_address
      formData.value.description = data.description
      formData.value.environment = data.environment
      formData.value.status = data.status
      if (data.function_list != "") {
        checkedNodes.value = JSON.parse(data.function_list)
      }
      if (data.other_file === null || data.other_file === "") return
      files.value = JSON.parse(data.other_file)
    } finally {
      formLoading.value = false
    }
  }
}
defineExpose({ open }) // 提供 open 方法，用于打开弹窗


const step1 = ref(true)
const step2 = ref(false)
const active = ref(0)
const emit = defineEmits(['success']) // 定义 success 事件，用于操作成功后的回调


/** 下一步 */
const Next = async () => {
  // 校验表单
  if (!formRef) return
  const valid = await formRef.value.validate()
  if (!valid) return
  // 提交请求
  try {
    active.value = 1
    step1.value = false
    step2.value = true
    nodeShow.value = false
    nodeData.value = {
      name: '',
      code: '',
      description: '',
      status: '',
      developerId: ''
    }
    nodeRef.value?.resetFields()
    getTree(formData.value.version)
  } finally {
  }
}
/** 上一步 */
const Back = () => {
  active.value = 0
  step1.value = true
  step2.value = false
}

/** 获取版本列表 */
const versionList = ref([])
const getversionList = async () => {
  const data = await TestApi.getVersion({ projectId: projectId })
  versionList.value = data
}
const uploadRef = ref()
const files = ref([])
const importUrl =
  import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/testManager/testForm/verify'
const uploadHeaders = ref() // 上传 Header 头
/** 上传错误提示 */
const submitFormError = (): void => {
  message.error('上传失败，请您重新上传！')
  formLoading.value = false
}
/** 文件数超出提示 */
const handleExceed = (): void => {
  message.error('最多只能上传一个文件！')
}
/** 文件上传成功 */
const submitFormSuccess = (response: any, file, fileList) => {
  if (response.code !== 200) {
    message.error(response.msg)
    formLoading.value = false
    return
  }
}
const handlePreview = async (file) => {
  window.open(file.url)
}

const dataSource = ref([])
const defaultProps = {
  children: 'children',
  label: 'name',
}
const treeRef = ref()
const checkedNodes = ref([])
const editDisabled = ref(false)
/** 获取需求树 */
const getTree = async (version) => {
  const data = await TestApi.getDemandTree({ id: version })
  if (!data) return
  if (formType.value === 'view') {
    editDisabled.value = true
  }
  dataSource.value = [data]
}
const nodeData = ref({
  name: '',
  code: '',
  description: '',
  status: '',
  developerId: ''
})
const statusList = ref([] as any)
const dutyList = ref([] as any)
const nodeRef = ref() // 表单 Ref
const nodeShow = ref(false)
// 获取状态列表
const getStatusList = () => {
  statusList.value = [
    {
      label: '新建',
      value: 1
    },
    {
      label: '测试中',
      value: 2
    },
    {
      label: '测试通过',
      value: 3
    },
    {
      label: '测试不通过',
      value: 4
    },
    {
      label: '禁用',
      value: 5
    }
  ]
}
// 获取开发责任人列表
const getDutyList = async () => {
  let data = await DemandApi.getProjectDevMember({ projectId: projectId })
  dutyList.value = data
}
/** 节点点击 */
const handleNodeClick = async (data) => {
  if (data.isRoot) {
    return
  }
  let result = {} as any
  if (data.id) {
    result = await TestApi.getDemandInfo({ id: data.id })
  } else {
    result = data
  }
  nodeShow.value = true
  nodeData.value = {
    ...result,
    name: result.name || data.name,
    status: statusList.value.find((s) => s.value == result?.status)?.label || '',
    developerId: dutyList.value.find((s) => s.id == result?.developerId)?.nickname || ''
  }
}
/** 过滤 */
const filterNode = (value, data) => {
  if (!value) return true
  return data.label.includes(value)
}

const submitDisabled = ref(false)
/** 提交 */
const submitForm = async () => {
  // 校验表单
  if (!formRef) return
  const valid = await formRef.value.validate()
  if (!valid) return
  // 提交请求
  uploadHeaders.value = {
    Authorization: 'Bearer ' + getAccessToken(),
    'tenant-id': getTenantId()
  }
  formLoading.value = true
  submitDisabled.value = true
  uploadRef.value!.submit()
  try {
    active.value = 1
    step1.value = false
    step2.value = true
    const data = new FormData()
    const params = {
      projectId: projectId,
      ...formData.value,
      function_list: JSON.stringify(treeRef.value.getCheckedKeys()),
    }

    if (files.value.length) {
      files.value.forEach((item) => {
        if (item.raw) {
          data.append(`files`, item.raw)
        } else {
          data.append(`files`, new Blob([item.url], { type: '' }))
        }
      })
    } else {
      data.append('files', new Blob([], { type: '' }))
    }
    if (formType.value === 'create') {
      data.append(
        'createReqVO',
        new Blob([JSON.stringify(params)], { type: 'application/json' })
      )
      await TestApi.createTest(data)
      message.success(t('common.createSuccess'))
    } else {
      data.append(
        'editReqVO',
        new Blob([JSON.stringify(params)], { type: 'application/json' })
      )
      await TestApi.updateTest(data)
      message.success(t('common.updateSuccess'))
    }
    dialogVisible.value = false
    // 发送操作成功的事件
    emit('success')
  } finally {
    formLoading.value = false
    submitDisabled.value = false
  }
}

</script>

<style scoped lang="scss">
.test-form {
  padding-top: 3%;
}

.test-tree {
  width: 100%;
  display: flex;
}

.test-form-footer {
  display: flex;
  justify-content: center;
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}

.num {
  color: var(--el-color-primary);
  border-radius: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  // margin: 0 0px 0 0px;
  font-size: 12px;
}

.disabled {
  width: 100%;
  cursor: not-allowed;
}

.tree-node {
  display: flex;
  align-items: center;
}

:deep(.el-tree) {
  padding: 10px 10px 10px 0;

  .el-tree-node {
    .el-tree-node__content {
      // display: flex;
      // justify-content: space-between;
    }

    i.el-tree-node__expand-icon {
      svg {
        display: none;
      }
    }

    i.el-tree-node__expand-icon {
      display: none;
    }
  }

  .el-tree-node.is-current {
    .el-tree-node__content {
      small {
        color: #5e7ce0;
      }
    }

    .el-tree-node__children {
      small {
        color: unset;
      }
    }
  }

  /* ^ 树节点 */
  .el-tree-node {
    position: relative;
    width: auto;
    padding-left: 13px;

    &::before {
      width: 1px;
      height: 100%;
      content: '';
      position: absolute;
      top: -38px;
      bottom: 0;
      left: 0;
      right: auto;
      border-width: 1px;
      border-left: 1px solid #b8b9bb;
    }

    &::after {
      width: 13px;
      height: 13px;
      content: '';
      position: absolute;
      z-index: 0;
      left: 0;
      right: auto;
      top: 12px;
      bottom: auto;
      border-width: 1px;
      border-top: 1px solid #b8b9bb;
    }

    .el-tree-node__content {
      position: relative;
      z-index: 1;
      padding-left: 0 !important;
    }

    .el-tree-node__children {
      padding-left: 12px;
    }

    &:last-child::before {
      height: 50px;
    }
  }

  >.el-tree-node {
    padding-left: 0;

    &::before {
      border-left: none;
    }

    &::after {
      border-top: none;
    }
  }

}


:deep(.disabled-tree) {
  .el-checkbox {
    pointer-events: none;
    cursor: not-allowed;
  }

  .el-checkbox__input {
    .el-checkbox__inner {
      // 禁用的样式
      background-color: rgb(237, 242, 252);
      border-color: rgb(217, 217, 217);
    }

    &.is-checked {

      // 勾选状态下的样式,不加的话禁用时勾选是灰色的
      .el-checkbox__inner {
        background-color: rgb(49, 56, 69);
        border-color: rgb(49, 56, 69);
      }
    }
  }
}
</style>
